package com.dippy.shiro;

import com.dippy.entity.User;
import com.dippy.service.UserService;
import com.dippy.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class AccountRealm extends AuthorizingRealm {

    // 用于解析jwt
    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private UserService userService;

    /**
     * 判断token是否是jwt的原始token,防止jwt生成的token被修改
     * @param token
     * @return
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }

    /**
     * 授权
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }

    /**
     * 认证
     *      编写登录逻辑
     *          1.获取token，解析出jwt
     *          2.通过解析jwt获取userId
     *          3.通过id查出用户
     *          4.判断用户是否存在
     *          5.交给shiro处理
     *
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // token强制转成jwttoken,
        // 之后进入jwtFilter的过滤onAccessDenied方法，进行判断jwt是否正确，过期与否，被改过没有等问题
        JwtToken jwtToken = (JwtToken) token;

        // 获取token的信息，getPrincipal里面包含token的信息，
        Claims claim = jwtUtils.getClaimByToken((String) jwtToken.getPrincipal());

        // 解析出用户id
        String userId = claim.getSubject();

        User user = userService.getById(Long.valueOf(userId));
        // user有问题时
        if (user == null) {
            throw new UnknownAccountException("账户不存在");
        }
        if (user.getStatus() == -1) {
            throw new LockedAccountException("账户被锁定了");
        }

        // user没问题时
        // 交给shiro处理，不过要注意不要暴露私密信息
        AccountProfiles profiles = new AccountProfiles();
        BeanUtils.copyProperties(user,profiles);// 用工具类把原数据user赋值给profiles

        return new SimpleAuthenticationInfo(profiles,jwtToken.getCredentials(),getName());
    }
}
